perm filename SNAILR.SAI[AL,HE] blob sn#241881 filedate 1976-10-13 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00006 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	file_switch and file record delcarations
C00003 00003	make_file_name, open_file, copy_file_record, clear_file_record
C00006 00004	scan_command, upper_case
C00008 00005	!	got_file (returns false for null file spec)
C00012 00006	!	execution
C00015 ENDMK
C⊗;
comment file_switch and file record delcarations;

require "[][]" delimiters;

		record_class
file_switch(
		string
    name;
		integer
    octal,
    decimal;
		record_pointer(file_switch)
    next
);
		record_class
file(
		integer
    chn;			comment channel on which file accessible;
		string
    name,
    ext,
    ppn,
    device,
    def_ext;
		boolean
    out;
		integer
    mode,			comment OPEN type info;
    eof,
    brchr,
    count,
    in_bfrs,
    out_bfrs;
		record_pointer(file)
    next;
		record_pointer(file_switch)
    switches
);
comment make_file_name, open_file, copy_file_record, clear_file_record;

string procedure make_file_name(record_pointer(file) F);
    return(if length(file:name[F])=0
	then null
	else (file:name[F] & "." & file:ext[F] & file:ppn[F]));

boolean procedure open_file(record_pointer(file) F);
    begin string file_name;
    if file:chn[F] < 0 then file:chn[F] ← getchan;
    if length(file:device[F])=0 then file:device[F] ← "DSK";
    open(file:chn[F], file:device[F], file:mode[F], file:in_bfrs[F],
		file:out_bfrs[F], file:count[F], file:brchr[F], file:eof[F]);
    if file:eof[F] then
	begin release(file:chn[F]); file:chn[F] ← -1; return(false) end;
    file_name ← make_file_name(F);
    if file:out[F]
	then enter(file:chn[F], file_name, file:eof[F])
	else lookup(file:chn[F], file_name, file:eof[F]);
    return(¬file:eof[F]);
    end;

procedure copy_file_record(record_pointer(file) dup, original);
    begin
    forlc field ← (chn, name, ext, ppn, device, def_ext, out, mode, eof, brchr,
		   count, in_bfrs, out_bfrs, next, switches)
	doc [file:field[dup] ← file:field[original];] endc
    end;

procedure clear_file_record(record_pointer(file) F);
    begin
    forlc field ← (chn, name, ext, ppn, device, def_ext)
	doc [file:field[F] ← null;] endc
    forlc field ← (out, mode, eof, brchr, count, in_bfrs, out_bfrs)
	doc [file:field[F] ← 0;] endc
    forlc field ← (next, switches)
	doc [file:field[F] ← null_record;] endc
    end;
comment scan_command, upper_case;

record_pointer(file) procedure scan_command(string s;
		record_pointer(file) rel, lst(null_record), swap(null_record));
begin "scanner"

		define
!	=[comment],
tab	='11,
lf	='12,
cr	='15,
space	='40;
		integer
break,
ignore_blanks_break,
pass_digits_break,
file_name_break,
ppn_break,
case_conversion;
		boolean
saw_file;
		record_pointer(file)
src,
F;

string procedure upper_case(string s);
    begin integer temp; return(scan(s, case_conversion, temp)) end;
!	got_file (returns false for null file spec);

boolean procedure got_file(reference string s; reference integer break;
		record_pointer(file) F);
    begin string word; record_pointer(file_switch) FS, FS1;

    integer procedure ignore_blanks(reference string s);
	begin integer break; scan(s, ignore_blanks_break, break); return(break) end;

    string procedure filwrd;
	begin ignore_blanks(s); return(scan(s, file_name_break, break)) end;

    word ← filwrd;  file:chn[F] ← -1;	! file has not been opened flag;
    if (break=0 ∨ break=lf ∨ break=cr ∨ break="," ∨ break="←") and length(word)=0
	then return(false);
    if break=":" then begin file:device[F] ← word; word ← filwrd end;
    file:name[F] ← word;
    if break="." then file:ext[F] ← filwrd;
    if break="[" then
	begin
	ignore_blanks(s); file:ppn[F] ← "[" & scan(s, ppn_break, break) & "]";
	if break="]" then begin ignore_blanks(s); break ← lop(s) end;
	end;
    if break="/" or break="(" then
	begin integer chr;
	do  begin "switches" string sign, digits;
	    chr ← ignore_blanks(s);  sign ← null;
	    if chr=")" then done;
	    if (FS1 ← FS)=null_record
		then FS ← file:switches[F] ← new_record(file_switch)
		else FS ← file_switch:next[FS1] ← new_record(file_switch);
	    if chr="+" ∨ chr="-" then begin sign←lop(s); chr←ignore_blanks(s) end;
	    if "0" ≤ chr ≤ "9" then
		begin
		digits ← sign & scan(s, pass_digits_break, chr);
		file_switch:octal[FS] ← cvo(digits);
		file_switch:decimal[FS] ← cvd(digits);
		sign ← null; chr ← ignore_blanks(s);
		end;
	    if sign then file_switch:octal[FS] ← file_switch:decimal[FS]
		← cvd(sign & "1");
	    file_switch:name[FS] ← lop(s); ignore_blanks(s);
	    if break="/" then chr ← lop(s);  ! skip the break character;
	    file_switch:name[FS] ← upper_case(file_switch:name[FS]);
	    end "switches"
	until (break="(" and chr=")") or (break≠"(" and chr≠"/");
	if break="(" and chr=")" then
	    begin chr ← lop(s); ignore_blanks(s); chr ← lop(s) end;
	break ← chr;
	end;
    if length(file:device[F])=0 then file:device[F] ← "DSK";
    return(true)
    end;
!	execution;

								setbreak(
ignore_blanks_break ← getbreak,	space & tab, cr, "XRK");
								setbreak(
pass_digits_break ← getbreak,	"0123456789", cr, "XRK");
								setbreak(
file_name_break ← getbreak,	"!←(/[:.," & lf, cr, "ISK");
								setbreak(
ppn_break ← getbreak,		"!←(/]" & lf, cr, "ISK");
								setbreak(
case_conversion ← getbreak,	null, null, "ISK");


saw_file ← got_file(s, break, F ← new_record(file)); file:out[F] ← true;
if break="!"
    then usererr(0, 0, "SNAILR:  ""!"" not yet implemented.")
    else if ¬(break="," or break="←")
	then usererr(0, 0, "SNAILR:  command line error")
	else
	    begin
	    if ¬saw_file then file:eof[F] ← true;	! indicates file not seen;
	    if rel≠null_record then copy_file_record(rel, F)
	    end;
if lst≠null_record then file:eof[lst] ← true;
if break="," and (saw_file ← got_file(s, break, F ← new_record(file))) then
    begin
    file:out[F] ← true;
    if lst≠null_record then
	begin
	if saw_file then file:eof[F] ← false;
	copy_file_record(lst, F)
	end
    end;
if break≠"←" then usererr(0, 0, "SNAILR:  command line error");
src ← null_record;

begin "source loop" record_pointer(file) F1;
do  begin
    if ¬got_file(s, break, F ← new_record(file)) then file:eof[F] ← false;
    if src=null_record
	then src ← F1 ← F
	else begin file:next[F1] ← F; F1 ← F end;
    if ¬(break="," ∨ break=cr ∨ break=lf ∨ break=0)
	then usererr(0, 0, "SNAILR:  command line error");
    end
until break=lf ∨ break=cr ∨ break=0;
end "source loop";

relbreak(ignore_blanks_break);
relbreak(pass_digits_break);
relbreak(file_name_break);
relbreak(ppn_break);
relbreak(case_conversion);

return(src);
end "scanner";

require unstack_delimiters;